import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus } from '@nestjs/common';
import { QueryFailedError } from 'typeorm';
import { BusinessException } from '../exceptions/biz.exception';
import { FastifyReply } from 'fastify';
import { ErrorEnum } from '~/constants/error-code.constant';
interface myError {
  readonly status: number;
  readonly statusCode?: number;

  readonly message?: string;
}
function isMyError(exception: unknown): exception is myError {
  return (
    typeof exception === 'object' &&
    exception !== null &&
    ('status' in exception || 'statusCode' in exception)
  );
}
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const status = this.getStatus(exception);
    const message = this.getErrorMessage(exception);
    const response = ctx.getResponse<FastifyReply>();
    const apiErrorCode = exception instanceof BusinessException ? exception.getErrorCode() : status;
    const resBody: IBaseResponse = {
      code: apiErrorCode,
      message,
      data: null
    };

    response.status(status).send(resBody);
  }
  getErrorMessage(exception: unknown): string {
    if (exception instanceof HttpException) {
      return exception.message;
    } else if (exception instanceof QueryFailedError) {
      return exception.message;
    }
    if (typeof exception === 'string') {
      return exception;
    }
    if ((exception as any).response && (exception as any).response.message) {
      return (exception as any).response.message as string;
    }
    if ((exception as any).message) {
      return (exception as any).message as string;
    }
    return ErrorEnum.SERVER_ERROR;
  }
  getStatus(exception: unknown): number {
    if (exception instanceof HttpException) {
      return exception.getStatus();
    }

    if (exception instanceof QueryFailedError) {
      return HttpStatus.INTERNAL_SERVER_ERROR;
    }

    if (isMyError(exception)) {
      return exception.status ?? exception.statusCode;
    }

    return HttpStatus.INTERNAL_SERVER_ERROR;
  }
}
